package com.example.smartpark.interceptor;

import com.alibaba.fastjson2.JSON;
import com.example.smartpark.common.Result;
import com.example.smartpark.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * JWT拦截器
 * 用于拦截需要认证的请求，验证JWT令牌
 */
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {

    /**
     * 前置处理：在请求处理之前进行拦截
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param handler  处理器对象
     * @return 是否放行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 如果是OPTIONS请求，放行（预检请求）
        if ("OPTIONS".equals(request.getMethod())) {
            return true;
        }

        // 从请求头中获取Authorization
        String authHeader = request.getHeader("Authorization");
        log.debug("验证JWT令牌：{}", authHeader);

        // 检查是否存在Authorization头
        if (!StringUtils.hasText(authHeader) || !authHeader.startsWith("Bearer ")) {
            log.warn("未提供有效的Authorization头");
            responseError(response, 401, "未提供有效的令牌");
            return false;
        }

        // 提取token
        String token = authHeader.substring(7);
        
        // 验证token
        if (!JwtUtils.validateToken(token)) {
            log.warn("无效的JWT令牌");
            responseError(response, 401, "无效的令牌");
            return false;
        }

        // 获取用户ID
        Integer userId = JwtUtils.getUserIdFromToken(token);
        if (userId == null) {
            log.warn("无法从令牌中提取用户ID");
            responseError(response, 401, "无效的令牌");
            return false;
        }

        // 在请求属性中设置用户ID，方便后续使用
        request.setAttribute("userId", userId);
        log.debug("JWT令牌验证通过，userId={}", userId);
        
        return true;
    }

    /**
     * 响应错误信息
     *
     * @param response 响应对象
     * @param code     错误码
     * @param message  错误信息
     */
    private void responseError(HttpServletResponse response, int code, String message) {
        try {
            response.setContentType("application/json;charset=UTF-8");
            response.setStatus(code);
            response.getWriter().write(JSON.toJSONString(Result.error(code, message)));
        } catch (IOException e) {
            log.error("响应错误信息失败", e);
        }
    }
} 